/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * JLevelPanel.java
 *
 * Created on 2010-apr-27, 13:08:11
 */

package foalvleditor.gui;

import foalvleditor.core.impl.AppSettingsModel;
import foalvleditor.core.impl.LevelModel;
import foalvleditor.core.impl.SelectionModel;
import foalvleditor.gameobjects.AbstractGameObject;
import foalvleditor.gameobjects.AbstractGameObject.ObjectType;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.List;

/**
 *
 * @author fish
 */
public class JLevelPanel extends javax.swing.JPanel {

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;
	private static final int snappingDistance = 10;
    private static final int objSnapDistance = 5;
    private static LevelModel levelModel=LevelModel.getInstance();
    private static SelectionModel selectionModel=SelectionModel.getInstance();
    private static AppSettingsModel settings=AppSettingsModel.getInstance();
    private transient List<AbstractGameObject> level;
    private AbstractGameObject background;
    private transient boolean doubleClicked=false;

    /** Creates new form JLevelPanel */
    public JLevelPanel() {
        super();
        this.setPreferredSize(new Dimension(480,320));
        this.setBackground(Color.darkGray);
        initComponents();
    }

    /**
     * Paints the level (i.e. converts the list into onscreen icons)
     *
     * @input ArrayList<AbstractGameObject> editedLevel
     * @output Graphics
     */

    @Override
    protected void paintComponent(Graphics g){
        Graphics2D g2=(Graphics2D)g;
        super.paintComponent(g2);
        level=levelModel.getLevel();
        background=levelModel.getBackground();

        // paints the background
        if (background!=null) {
            g2.drawImage(background.getBitmap().getBufferedImage(), 0, 0, null);
        }

        // paints the 16x16-grid
        if (settings.isGridShown())
        {
        g2.setColor(Color.LIGHT_GRAY);
             int xgrid=0,ygrid=0;
             while (xgrid<480){
                 g2.drawLine(xgrid, 0, xgrid, 320);
                 xgrid+=16;
             }
             while (ygrid<320){
                 g2.drawLine(0, ygrid, 480, ygrid);
                 ygrid+=16;
             }
        }

        if (level!=null) {
            // paints all the other objects
            for (int j=3; j>=0; j--)
                {
                for(int i=0; i<level.size(); i++)
                {
                    AbstractGameObject gob=level.get(i);
                    gob.getType();
					if (gob.getType()==ObjectType.BITMAPOBJECT && gob.getLayer()==j)
                        g2.drawImage(gob.getBitmap().getBufferedImage(), gob.getPosition().x, gob.getPosition().y, null);
                    }

                }
             }

            // paints the yellow border around the selected object
            if (selectionModel.getSelected().size()>0)
            {
                for (int j=0; j<selectionModel.getSelected().size(); j++)
                {
                    AbstractGameObject gob=selectionModel.getSelected().get(j);
                    g2.setColor(Color.YELLOW);
                    g2.drawRect(gob.getPosition().x-1, gob.getPosition().y-1, gob.getWidth()+2, gob.getHeight()+2);
                }

            }

        }



    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {

        setName("Form"); // NOI18N
        setPreferredSize(new java.awt.Dimension(480, 320));
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                formMouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                formMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                formMouseReleased(evt);
            }
        });
        addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                formMouseDragged(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 480, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 320, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void formMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseClicked
    }//GEN-LAST:event_formMouseClicked

    private void formMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMousePressed
      // selects the object
        level=levelModel.getLevel();
        for (int i=0; i<level.size(); i++)
        {   level.get(i).getType();
		if (evt.getX() >= level.get(i).getPosition().x &&
                evt.getX() <= level.get(i).getPosition().x+level.get(i).getWidth() &&
                evt.getY() >= level.get(i).getPosition().y &&
                evt.getY() <= level.get(i).getPosition().y+level.get(i).getHeight() &&
                (level.get(i).getType()!=ObjectType.BACKGROUND))
            {
                if (selectionModel.getSelected().size() > 0) selectionModel.deselectAll();
                selectionModel.select(level.get(i));
                levelModel.getView().repaintPanel(level.get(i));
            }
        }

        //if right button is pressed, the popup menu is opened
        if (selectionModel.getSelected().size()==1 && evt.getButton()==MouseEvent.BUTTON3)
            {
                AbstractGameObject ago=selectionModel.getSelected().get(0);
                int xPos=levelModel.getView().getFrame().getMousePosition().x;
                int yPos=levelModel.getView().getFrame().getMousePosition().y;
                JObjectPopupMenu jopm=new JObjectPopupMenu(ago, xPos, yPos);
                jopm.show(levelModel.getView().getFrame(), xPos, yPos);
                selectionModel.deselect(ago);
                levelModel.getView().repaintPanel(ago);
        }

        // if doubleclicked, the object is hard selected

        if (selectionModel.getSelected().size()==1 && evt.getClickCount()==2)
            this.doubleClicked=true;
    }//GEN-LAST:event_formMousePressed

    private void formMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseDragged
  if (selectionModel.getSelected().size()==1)
        {

         // makes the object dragged by mouse in the middle
         AbstractGameObject goa=selectionModel.getSelected().get(0);
         int mouseXPos=evt.getX(), mouseYPos=evt.getY();
         mouseXPos-=(goa.getWidth()/2);
         mouseYPos-=(goa.getHeight()/2);
         level=levelModel.getLevel();

         // removes the object if placed outside level boundaries
         if(mouseXPos>480 || mouseYPos>320 || mouseXPos<-20 || mouseYPos<-20)
            {
             levelModel.removeObject(goa);
             }
         else{

             // snap to 16x16 grid
             if (settings.isSnappingToGrid()){
                int xSnapped=mouseXPos%16, ySnapped=mouseYPos%16;
                if (xSnapped < snappingDistance){
                    mouseXPos-=xSnapped;
                }
                if (ySnapped < snappingDistance){
                    mouseYPos-=ySnapped;
                }
             }

             // snap to existing objects within 3x3-radius
             if (settings.isSnappingToObjects())
             {
             for (int i=0; i<level.size(); i++)
                {
                 AbstractGameObject goc=level.get(i);
                 if (mouseXPos-(goc.getPosition().x+goc.getWidth())<objSnapDistance
                         && mouseXPos-(goc.getPosition().x+goc.getWidth())>-objSnapDistance)
                     mouseXPos=goc.getPosition().x+goc.getWidth();
                 if (mouseXPos+goa.getWidth()-goc.getPosition().x<objSnapDistance
                         && mouseXPos+goa.getWidth()-goc.getPosition().x>-objSnapDistance)
                     mouseXPos=goc.getPosition().x-goa.getWidth();
                 if (mouseYPos-(goc.getPosition().y+goc.getHeight())<objSnapDistance
                         && mouseYPos-(goc.getPosition().y+goc.getHeight())>-objSnapDistance)
                     mouseYPos=goc.getPosition().y+goc.getHeight();
                 if (mouseYPos+goa.getHeight()-goc.getPosition().y<objSnapDistance
                         && mouseYPos+goa.getHeight()-goc.getPosition().y>-objSnapDistance)
                     mouseYPos=goc.getPosition().y-goa.getHeight();
                 if (mouseXPos-goc.getPosition().x<objSnapDistance
                         && mouseXPos-goc.getPosition().x>-objSnapDistance)
                     mouseXPos=goc.getPosition().x;
                 if (mouseYPos-goc.getPosition().y<objSnapDistance
                         && mouseYPos-goc.getPosition().y>-objSnapDistance)
                     mouseYPos=goc.getPosition().y;

             }
             }
            goa.setPosition(new Point(mouseXPos, mouseYPos));
            levelModel.getView().repaintPanel(goa);
            }
         levelModel.setChanged(true);
         levelModel.getView().repaintAll();
        }
    }//GEN-LAST:event_formMouseDragged

    private void formMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseReleased

        //this happens when the mouse is released
        if (selectionModel.getSelected().size()==1 && !doubleClicked)
        {
            AbstractGameObject disposable=selectionModel.getSelected().get(0);
            selectionModel.deselect(disposable);
            levelModel.getView().repaintPanel(disposable);
            levelModel.getView().repaintAll();}

        //this happens when the object is hard selected
        else if (selectionModel.getSelected().size()==1 && doubleClicked)
        {   levelModel.getView().hardSelectPanel(selectionModel.getSelected().get(0));
            levelModel.getView().repaintAll();
            doubleClicked=false;
        }

    }//GEN-LAST:event_formMouseReleased


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
}
